#ifndef __M_CONNECTION_H__
#define __M_CONNECTION_H__
// 引入muduo库的Protobuf消息分发器，用于根据消息类型分发到对应处理函数
#include "muduo/proto/dispatcher.h"
// 引入muduo库的Protobuf编解码器，用于消息的序列化和反序列化
#include "muduo/proto/codec.h"
// 引入muduo库的日志模块，用于输出日志信息
#include "muduo/base/Logging.h"
// 引入muduo库的互斥锁，用于线程同步
#include "muduo/base/Mutex.h"
// 引入muduo库的事件循环类，用于处理IO事件和定时器等
#include "muduo/net/EventLoop.h"
// 引入muduo库的TCP客户端类，用于建立和管理TCP连接
#include "muduo/net/TcpClient.h"
// 引入muduo库的事件循环线程类，用于创建包含事件循环的线程
#include "muduo/net/EventLoopThread.h"
// 引入muduo库的倒计时门闩，用于线程同步，等待某个事件完成
#include "muduo/base/CountDownLatch.h"

// 引入信道类头文件，Connection类需要管理Channel对象
#include "mq_channel.hpp"
// 引入工作器类头文件，Connection依赖AsyncWorker提供的线程资源
#include "mq_worker.hpp"

namespace zdfmq
{
    /**
     * @brief 连接类，负责与消息队列服务器建立和管理TCP连接，是客户端与服务器通信的入口
     * 核心功能：封装TCP连接的建立、消息的发送与接收、信道的创建与关闭等，协调各组件协同工作
     * 设计思路：基于muduo网络库的TcpClient，结合Protobuf编解码器和分发器，实现高效的消息处理
     */
    class Connection
    {
    public:
        // 定义Connection的智能指针类型，方便管理对象生命周期，适合多线程环境
        using ptr = std::shared_ptr<Connection>;

        /**
         * @brief 构造函数，初始化连接相关资源，建立与服务器的连接
         * @param sip 服务器IP地址
         * @param sport 服务器端口号
         * @param worker 异步工作器指针，提供事件循环线程和线程池资源
         * 初始化流程：
         * 1. 初始化倒计时门闩(_latch)，用于等待连接建立完成
         * 2. 初始化TcpClient，指定事件循环、服务器地址和客户端名称
         * 3. 初始化消息分发器(_dispatcher)，设置未知消息的处理函数
         * 4. 初始化Protobuf编解码器(_codec)，关联分发器的消息处理函数
         * 5. 注册特定类型消息的处理回调函数（basicCommonResponse、basicConsumeResponse）
         * 6. 设置TcpClient的消息回调和连接回调函数
         * 7. 发起连接请求，并阻塞等待连接建立成功
         */
        Connection(const std::string &sip, int sport, const AsyncWorker::ptr &worker) : _latch(1),
                                                                                        // 初始化TcpClient，使用worker中事件循环线程的事件循环
                                                                                        _client(worker->loopthread.startLoop(), muduo::net::InetAddress(sip, sport), "Client"),
                                                                                        // 初始化分发器，绑定未知消息处理函数onUnknownMessage
                                                                                        _dispatcher(std::bind(&Connection::onUnknownMessage, this, std::placeholders::_1,
                                                                                                              std::placeholders::_2, std::placeholders::_3)),
                                                                                        // 初始化编解码器，绑定分发器的消息处理函数
                                                                                        _codec(std::make_shared<ProtobufCodec>(std::bind(&ProtobufDispatcher::onProtobufMessage, &_dispatcher,
                                                                                                                                         std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))),
                                                                                        _worker(worker),
                                                                                        // 初始化信道管理器，用于管理当前连接下的所有信道
                                                                                        _channel_manager(std::make_shared<ChannelManager>())
        {

            // 注册basicCommonResponse类型消息的处理回调函数
            _dispatcher.registerMessageCallback<basicCommonResponse>(std::bind(&Connection::basicResponse, this,
                                                                               std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

            // 注册basicConsumeResponse类型消息的处理回调函数
            _dispatcher.registerMessageCallback<basicConsumeResponse>(std::bind(&Connection::consumeResponse, this,
                                                                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));

            // 设置TcpClient的消息回调函数，收到消息时交给编解码器处理
            _client.setMessageCallback(std::bind(&ProtobufCodec::onMessage, _codec.get(),
                                                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
            // 设置TcpClient的连接回调函数，处理连接建立和断开事件
            _client.setConnectionCallback(std::bind(&Connection::onConnection, this, std::placeholders::_1));

            // 发起连接请求
            _client.connect();
            // 阻塞等待，直到连接建立成功（_latch倒计时变为0）
            _latch.wait();
        }

        /**
         * @brief 打开一个新的信道
         * 流程：
         * 1. 通过信道管理器创建一个新的信道，关联当前TCP连接和编解码器
         * 2. 调用信道的openChannel方法，向服务器发送打开信道请求
         * 3. 根据打开结果返回信道指针或空指针
         * @return 成功打开的信道智能指针，失败则返回空指针
         */
        Channel::ptr openChannel()
        {
            Channel::ptr channel = _channel_manager->create(_conn, _codec);
            bool ret = channel->openChannel();
            if (ret == false)
            {
                DLOG("打开信道失败！");
                return Channel::ptr();
            }
            return channel;
        }

        /**
         * @brief 关闭指定的信道
         * 流程：
         * 1. 调用信道的closeChannel方法，向服务器发送关闭信道请求
         * 2. 从信道管理器中移除该信道
         * @param channel 要关闭的信道智能指针
         */
        void closeChannel(const Channel::ptr &channel)
        {
            channel->closeChannel();
            _channel_manager->remove(channel->cid());
        }

    private:
        /**
         * @brief 处理服务器返回的basicCommonResponse类型响应
         * 功能：将响应消息分发到对应的信道
         * 流程：
         * 1. 根据响应消息中的信道ID(cid)，通过信道管理器查找对应的信道
         * 2. 若找到信道，调用信道的putBasicResponse方法，将响应添加到信道的响应映射表中
         * 3. 若未找到信道，输出日志信息
         * @param conn TCP连接指针
         * @param message 服务器返回的basicCommonResponse消息智能指针
         * @param 时间戳（未使用）
         */
        void basicResponse(const muduo::net::TcpConnectionPtr &conn, const basicCommonResponsePtr &message, muduo::Timestamp)
        {
            // 根据消息中的cid查找对应的信道
            Channel::ptr channel = _channel_manager->get(message->cid());
            if (channel.get() == nullptr)
            {
                DLOG("未找到信道信息！");
                return;
            }
            // 将响应添加到信道的响应映射表，唤醒等待该响应的线程
            channel->putBasicResponse(message);
        }

        /**
         * @brief 处理服务器推送的basicConsumeResponse类型消息（消费消息）
         * 功能：将消息处理任务异步提交到线程池
         * 流程：
         * 1. 根据消息中的信道ID(cid)，通过信道管理器查找对应的信道
         * 2. 若找到信道，将消息处理任务（调用channel->consume(message)）封装为lambda表达式，提交到线程池
         * 3. 若未找到信道，输出日志信息
         * 设计目的：消息处理可能耗时，通过线程池异步处理，避免阻塞事件循环线程
         * @param conn TCP连接指针
         * @param message 服务器推送的basicConsumeResponse消息智能指针
         * @param 时间戳（未使用）
         */
        void consumeResponse(const muduo::net::TcpConnectionPtr &conn, const basicConsumeResponsePtr &message, muduo::Timestamp)
        {
            // 根据消息中的cid查找对应的信道
            Channel::ptr channel = _channel_manager->get(message->cid());
            if (channel.get() == nullptr)
            {
                DLOG("未找到信道信息！");
                return;
            }
            // 将消息处理任务提交到线程池，异步执行
            _worker->pool.push([channel, message]()
                               { channel->consume(message); });
        }

        /**
         * @brief 处理未知类型的消息
         * 功能：当收到未注册的消息类型时，输出日志并关闭连接
         * @param conn TCP连接指针
         * @param message 未知类型的消息智能指针
         * @param 时间戳（未使用）
         */
        void onUnknownMessage(const muduo::net::TcpConnectionPtr &conn, const MessagePtr &message, muduo::Timestamp)
        {
            LOG_INFO << "onUnknownMessage: " << message->GetTypeName();
            conn->shutdown();
        }

        /**
         * @brief 处理TCP连接事件（连接建立或断开）
         * 功能：在连接建立时唤醒等待的线程，在连接断开时重置连接指针
         * 流程：
         * 1. 若连接建立成功（conn->connected()为true），调用_countDownLatch的countDown()方法，唤醒等待连接的线程，并保存连接指针
         * 2. 若连接断开（conn->connected()为false），重置连接指针
         * @param conn TCP连接指针
         */
        void onConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            if (conn->connected())
            {
                _latch.countDown(); // 连接建立成功，倒计时减1，唤醒等待的线程
                _conn = conn;
            }
            else
            {
                // 连接关闭，重置连接指针
                _conn.reset();
            }
        }

    private:
        muduo::CountDownLatch _latch;       // 倒计时门闩，用于等待连接建立完成（初始值为1，连接建立后减为0）
        muduo::net::TcpConnectionPtr _conn; // 当前的TCP连接指针，连接建立后有效
        muduo::net::TcpClient _client;      // TCP客户端对象，用于管理与服务器的TCP连接
        ProtobufDispatcher _dispatcher;     // Protobuf消息分发器，根据消息类型分发到对应处理函数
        ProtobufCodecPtr _codec;            // Protobuf编解码器指针，负责消息的序列化和反序列化

        AsyncWorker::ptr _worker;             // 异步工作器指针，提供事件循环线程和线程池资源
        ChannelManager::ptr _channel_manager; // 信道管理器指针，用于管理当前连接下的所有信道
    };
}

#endif